import nodemailer from 'nodemailer';
import {
  AlertMessage,
  AlertLevel,
  AlertTarget,
  AlertConfig,
  AlertResult,
  ThrottleConfig
} from '../types/alert';

export class AlertService {
  private static instance: AlertService;
  private transporter: nodemailer.Transporter;
  private webhookUrl: string;
  private rateLimitMap = new Map<string, number>();

  private constructor() {
    // 初始化邮件发送器
    this.transporter = nodemailer.createTransport({
      host: process.env.SMTP_HOST,
      port: Number(process.env.SMTP_PORT),
      secure: process.env.SMTP_SECURE === 'true',
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS
      }
    });

    // 初始化webhook URL (例如企业微信或钉钉)
    this.webhookUrl = process.env.ALERT_WEBHOOK_URL || '';
  }

  public static getInstance(): AlertService {
    if (!AlertService.instance) {
      AlertService.instance = new AlertService();
    }
    return AlertService.instance;
  }

  // 发送告警
  private readonly defaultConfig: AlertConfig = {
    targets: [AlertTarget.EMAIL, AlertTarget.WEBHOOK],
    retryCount: 3,
    retryDelay: 1000,
    throttleInterval: 5 * 60 * 1000
  };

  // 限流配置
  private readonly throttleConfig: ThrottleConfig = {
    enabled: true,
    interval: 5 * 60 * 1000,
    maxAttempts: 3
  };

  public async sendAlert(
    alert: AlertMessage,
    config: Partial<AlertConfig> = {}
  ): Promise<AlertResult[]> {
    const mergedConfig = { ...this.defaultConfig, ...config };
    const results: AlertResult[] = [];

    // 添加默认字段
    const enrichedAlert: AlertMessage = {
      ...alert,
      level: alert.level || AlertLevel.ERROR,
      timestamp: alert.timestamp || new Date(),
      source: alert.source || 'system'
    };

    // 检查限流
    if (
      mergedConfig.throttleKey &&
      this.throttleConfig.enabled &&
      this.shouldThrottle(mergedConfig.throttleKey)
    ) {
      console.log(`Alert throttled for key: ${mergedConfig.throttleKey}`);
      return results;
    }

    // 发送到每个目标
    for (const target of mergedConfig.targets) {
      let result: AlertResult | null = null;
      let attempts = 0;

      while (attempts < (mergedConfig.retryCount || 1)) {
        try {
          switch (target) {
            case AlertTarget.EMAIL:
              await this.sendEmailAlert(enrichedAlert);
              result = { success: true, target, timestamp: new Date() };
              break;
            case AlertTarget.WEBHOOK:
              await this.sendWebhookAlert(enrichedAlert);
              result = { success: true, target, timestamp: new Date() };
              break;
            case AlertTarget.SMS:
              await this.sendSMSAlert(enrichedAlert);
              result = { success: true, target, timestamp: new Date() };
              break;
          }
          break; // 成功时退出重试循环
        } catch (error) {
          attempts++;
          if (attempts >= (mergedConfig.retryCount || 1)) {
            result = {
              success: false,
              target,
              error: error as Error,
              timestamp: new Date()
            };
          } else {
            await this.delay(mergedConfig.retryDelay || 1000);
          }
        }
      }

      if (result) {
        results.push(result);
      }
    }

    return results;
  }

  // 发送邮件告警
  private async sendEmailAlert(alert: AlertMessage): Promise<void> {
    if (alert.level === AlertLevel.CRITICAL) {
      process.env.ALERT_EMAILS_CRITICAL?.split(',').forEach(email => {
        if (!alertEmails.includes(email)) {
          alertEmails.push(email);
        }
      });
    }
    const alertEmails = process.env.ALERT_EMAILS?.split(',') || [];
    if (!alertEmails.length) {
      console.warn('No alert emails configured');
      return;
    }

    const mailOptions = {
      from: process.env.SMTP_FROM,
      to: alertEmails.join(','),
      subject: alert.title,
      text: alert.body,
      html: this.formatAlertHtml(alert)
    };

    try {
      await this.transporter.sendMail(mailOptions);
    } catch (error) {
      console.error('Failed to send email alert:', error);
      throw error;
    }
  }

  // 发送Webhook告警
  private async sendWebhookAlert(alert: AlertMessage): Promise<void> {
    if (!this.webhookUrl) {
      console.warn('No webhook URL configured');
      return;
    }

    try {
      const response = await fetch(this.webhookUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          msgtype: 'markdown',
          markdown: {
            title: alert.title,
            text: this.formatAlertMarkdown(alert)
          }
        })
      });

      if (!response.ok) {
        throw new Error(`Webhook request failed with status ${response.status}`);
      }
    } catch (error) {
      console.error('Failed to send webhook alert:', error);
      throw error;
    }
  }

  // 发送短信告警 (需要集成短信服务商的SDK)
  private async sendSMSAlert(alert: AlertMessage): Promise<void> {
    // TODO: 实现短信告警
    console.warn('SMS alert not implemented');
  }

  // 格式化HTML告警内容
  private formatAlertHtml(alert: AlertMessage): string {
    return `
      <div style="font-family: Arial, sans-serif; padding: 20px;">
        <h2 style="color: #d93025;">${alert.title}</h2>
        <pre style="background-color: #f8f9fa; padding: 15px; border-radius: 4px;">
          ${alert.body}
        </pre>
        <p style="color: #666;">
          Generated at ${new Date().toISOString()}
        </p>
      </div>
    `;
  }

  // 格式化Markdown告警内容
  private formatAlertMarkdown(alert: AlertMessage): string {
    return `
### ${alert.title}

\`\`\`
${alert.body}
\`\`\`

> Generated at ${new Date().toISOString()}
    `.trim();
  }

  // 延迟函数
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  // 清理过期的限流记录
  private cleanupThrottleMap(): void {
    const now = Date.now();
    for (const [key, time] of this.rateLimitMap.entries()) {
      if (now - time >= this.throttleConfig.interval) {
        this.rateLimitMap.delete(key);
      }
    }
  }

  // 定期清理限流记录
  private startCleanupInterval(): void {
    setInterval(() => {
      this.cleanupThrottleMap();
    }, this.throttleConfig.interval);
  }

  // 检查是否需要限流
  private shouldThrottle(key: string): boolean {
    const lastAlertTime = this.rateLimitMap.get(key);
    const now = Date.now();

    if (!lastAlertTime || (now - lastAlertTime) >= this.throttleConfig.interval) {
      this.rateLimitMap.set(key, now);
      return false;
    }

    return true;
  }
}
